#include <TensorFlowLite_ESP32.h>
/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/


#include "tensorflow/lite/micro/all_ops_resolver.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/micro/system_setup.h"
#include "tensorflow/lite/schema/schema_generated.h"

#include "main_functions.h"
#include "model.h"
#include "constants.h"
#include "output_handler.h"
#include <Arduino.h>


// Globals, used for compatibility with Arduino-style sketches.
// 翻译：全局变量，用于与Arduino风格的程序兼容。
namespace {
tflite::ErrorReporter* error_reporter = nullptr;
const tflite::Model* model = nullptr;
tflite::MicroInterpreter* interpreter = nullptr;
TfLiteTensor* input = nullptr;
TfLiteTensor* output = nullptr;
int inference_count = 0;

constexpr int kTensorArenaSize = 5000; // 这是分配给张量的内存大小。
uint8_t tensor_arena[kTensorArenaSize];
}  // namespace


  
// The name of this function is important for Arduino compatibility.
// 翻译：这个函数的名称对于Arduino兼容性很重要。
void setup() {

  // 翻译：设置日志记录。Google风格是避免全局或静态变量，因为生命周期不确定，但由于此处析构函数很简单，所以可以。
  static tflite::MicroErrorReporter micro_error_reporter; 
  error_reporter = &micro_error_reporter;

  // Map the model into a usable data structure. This doesn't involve any
  // copying or parsing, it's a very lightweight operation.
  // 翻译：将模型映射到可用的数据结构中。这不涉及任何复制或解析，这是一个非常轻量级的操作。
  model = tflite::GetModel(g_model);
  if (model->version() != TFLITE_SCHEMA_VERSION) {
    TF_LITE_REPORT_ERROR(error_reporter,
                         "Model provided is schema version %d not equal "
                         "to supported version %d.",
                         model->version(), TFLITE_SCHEMA_VERSION);
    return;
  }

  // This pulls in all the operation implementations we need.
  // NOLINTNEXTLINE(runtime-global-variables)
  // 翻译：此处包含所有所需的操作实现。
  static tflite::AllOpsResolver resolver;

  // Build an interpreter to run the model with.
  // 翻译：构建一个解释器来运行模型。
  static tflite::MicroInterpreter static_interpreter(
      model, resolver, tensor_arena, kTensorArenaSize, error_reporter);
  interpreter = &static_interpreter;

  // Allocate memory from the tensor_arena for the model's tensors.
  // 翻译：为模型的张量分配内存。
  TfLiteStatus allocate_status = interpreter->AllocateTensors();
  if (allocate_status != kTfLiteOk) {
    TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
    return;
  }

  // 获取模型的输入和输出张量的指针。
  input = interpreter->input(0);
  output = interpreter->output(0);


  printf("scaled:%f zeropoint:%f \n",input->params.scale,input->params.zero_point);

  // 翻译：跟踪我们已经进行了多少次推理。
  inference_count = 0;
}

// 标准化函数
float min_max_scaler(float value, float min, float max, float new_min, float new_max) {
    return ((value - min) / (max - min)) * (new_max - new_min) + new_min;
}

// 反归一化函数
float inverse_min_max_scaler(float normalized_value, float min, float max, float new_min, float new_max) {
    return ((normalized_value - new_min) / (new_max - new_min)) * (max - min) + min;
}

// The name of this function is important for Arduino compatibility.
float x0 = 611.0; // 转速
float x1 = 28.45; // 功率

// 定义最小值和最大值
float min_x0 = 611.0;     // 转速的最小值
float max_x0 = 1950.0;    // 转速的最大值
float min_x1 = 22.34;     // 功率的最小值
float max_x1 = 435.32;    // 功率的最大值

// 归一化范围
float new_min = -2.0;
float new_max =  2.0;

// 反归一化输出数据
  // 流量的最小值和最大值
  float min_flow = 0.0;
  float max_flow = 21.79;

  // 扬程的最小值和最大值
  float min_lift = 0.73;
  float max_lift = 9.96;

void loop() {
  // 翻译：计算一个x值，将其输入模型中。
  // 我们将当前的inference_count与每周期的推理次数进行比较，
  // 以确定模型训练时可能的x值的范围，并使用此值计算一个值。
  // float position = static_cast<float>(inference_count) /
  //                  static_cast<float>(kInferencesPerCycle);
  // float x = position * kXrange;

  // 设置x0 跟x1的 实例值 x0 转速 x1功率 输出的流量跟扬程 2.476839   1.1884611

  // 输入参数归一化 MinMaxScaler 范围为[-2,2]
  // 转速的最小值: 611.0, 最大值: 1950.0
  // 功率的最小值: 22.34, 最大值: 435.32
  // 流量的最小值: 0.0, 最大值: 21.79
  // 扬程的最小值: 0.73, 最大值: 9.96



  // 进行归一化
  float normalized_x0 = min_max_scaler(x0, min_x0, max_x0, new_min, new_max);
  float normalized_x1 = min_max_scaler(x1, min_x1, max_x1, new_min, new_max);

  // 打印量化参数
  printf("scaled:%f zeropoint:%f \n",input->params.scale,input->params.zero_point);
// 
  
  // // 量化输入数据
  // // 假设x0为转速，x1为功率
  // int8_t input_data[2];
  // // 量化输入数据
  // input_data[0] = (int8_t)((normalized_x0 / input->params.scale) + input->params.zero_point);
  // input_data[1] = (int8_t)((normalized_x1 / input->params.scale) + input->params.zero_point);
  // // 将量化后的输入放入模型的输入张量
  // input->data.int8[0] = input_data[0];
  // input->data.int8[1] = input_data[1];

  // printf("normalized_x0: %f, normalized_x1: %f\n", normalized_x0, normalized_x1);
  // printf("quantized_x0: %d, quantized_x1: %d\n", input_data[0], input_data[1]);


  // 不量化
  // 输入参数归一化后的即为输入值，不进行量化
  input->data.f[0] = x0; // 假设直接使用浮点值
  input->data.f[1] = x1; // 假设直接使用浮点值

  // 运行推理，并报告任何错误
  TfLiteStatus invoke_status = interpreter->Invoke();
  if (invoke_status != kTfLiteOk) {
      TF_LITE_REPORT_ERROR(error_reporter, "Invoke failed on x0: %f, x1: %f\n",
                          static_cast<double>(x0), static_cast<double>(x1));
      return;
  }

  // printf("scaled:%f zeropoint:%f \n",output->params.scale,output->params.zero_point);

  // // 量化输出
  // int8_t y_quantized[] = {output->data.int8[0], output->data.int8[1]};
  // // 反量化输出数据
  // float flow = (y_quantized[0] - output->params.zero_point)*output->params.scale; // 流量
  // float lift = (y_quantized[1] - output->params.zero_point)*output->params.scale; // 扬程


  // printf("y_quantized: %d, %d\n", y_quantized[0], y_quantized[1]);

  // 不量化
  // 直接访问浮点输出
  float flow = output->data.f[0]; // 流量
  float lift = output->data.f[1]; // 扬程

    // 进行反归一化
    float original_flow = inverse_min_max_scaler(flow, min_flow, max_flow, new_min, new_max);
    float original_lift = inverse_min_max_scaler(lift, min_lift, max_lift, new_min, new_max);

    // 输出结果
    printf("x0: %f, x1: %f, flow: %f, lift: %f\n", static_cast<double>(x0), static_cast<double>(x1), static_cast<double>(original_flow), static_cast<double>(original_lift));

  // 输出x y的值
  // printf("x: %f, y: %f\n", static_cast<double>(x), static_cast<double>(y));


  // 翻译：输出结果。对于支持的硬件目标，可以实现自定义HandleOutput函数。
  // HandleOutput(error_reporter, x, y);

  // Increment the inference_counter, and reset it if we have reached
  // the total number per cycle 
  // 翻译：递增inference_counter，并在我们达到每周期的总次数时重置它
  inference_count += 1;
  if (inference_count >= kInferencesPerCycle) inference_count = 0;
}

